package com.ch5;
//127.0.0.1
import ch1.TextFileIO;
import ch3.TCPClient;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;


public class TCPClientThreadFX extends Application {

  private TCPClient tcpClient;
  private Thread receiveThread;


  public static void main(String[] args) {
    launch(args);
  }



  private Button btnExit = new Button("退出");
  private Button btnSend = new Button("发送");
  private Button btnConnect = new Button("连接");

  private TextField tfSend = new TextField();
  private TextArea taDisplay = new TextArea();

  private TextField tfIP = new TextField();
  private TextField tfPort = new TextField();


  public void start(Stage primaryStage) throws IOException {

    BorderPane mainPane = new BorderPane();

    HBox topHBox = new HBox();
    topHBox.setSpacing(10);
    topHBox.setPadding(new Insets(10, 20, 10, 20));
    topHBox.setAlignment(Pos.CENTER);
    topHBox.getChildren().addAll(new Label("IP地址："),
            tfIP, new Label("端口："), tfPort, btnConnect);

    mainPane.setTop(topHBox);

    VBox vBox = new VBox();
    vBox.setSpacing(10);
    vBox.setPadding(new Insets(10, 20, 10, 20));
    vBox.getChildren().addAll(new Label("信息显示区："),
            taDisplay, new Label("信息输入区："), tfSend);
    VBox.setVgrow(taDisplay, Priority.ALWAYS);

    taDisplay.setWrapText(true);
    taDisplay.setEditable(false);
    mainPane.setCenter(vBox);

    HBox hBox = new HBox();
    hBox.setSpacing(10);
    hBox.setPadding(new Insets(10, 20, 10, 20));
    hBox.setAlignment(Pos.CENTER_RIGHT);
    hBox.getChildren().addAll(btnSend, btnExit);

    mainPane.setBottom(hBox);


    Scene scene = new Scene(mainPane, 700, 400);
    primaryStage.setScene(scene);
    primaryStage.show();

    btnExit.setOnAction(event -> {
      if (tcpClient != null) {
        //向服务器发送关闭连接的约定信息
        tcpClient.send("bye");
        tcpClient.close();
      }
      System.exit(0);
    });


    btnSend.setOnAction(event -> {
      String sendMsg = tfSend.getText();
      tcpClient.send(sendMsg);//向服务器发送一串字符
      taDisplay.appendText("客户端发送：" + sendMsg + "\n");
      tfSend.clear();
    });

    btnConnect.setOnAction(event -> {
      String ip = tfIP.getText().trim();
      String port = tfPort.getText().trim();

      try {
        //创建TCPClient实例
        tcpClient = new TCPClient(ip, port);

        receiveThread = new Thread(()->{
          String msg = null;
          while ((msg = tcpClient.receive()) != null) {
            String msgTemp = msg;
            Platform.runLater(() -> {
              taDisplay.appendText(msgTemp + "\n");
            });
          }
          Platform.runLater(() -> {
            taDisplay.appendText("对话已关闭！\n");
          });
        });

        receiveThread.start();

      } catch (Exception e) {
        taDisplay.appendText("服务器连接失败！" + e.getMessage() + "\n");
      }
    });

    tfSend.setOnKeyPressed(new EventHandler<KeyEvent>() {
      @Override
      public void handle(KeyEvent event) {
        if (event.getCode() == KeyCode.ENTER) {
          String msg = tfSend.getText();
          if (!msg.isEmpty() && tcpClient != null) {
            tcpClient.send(msg);
            taDisplay.appendText("客户端发送：" + msg + "\n");
            tfSend.clear();
          }
        }
      }
    });

    TextFileIO textFileIO = new TextFileIO();


    primaryStage.setOnCloseRequest(event -> {
      if (tcpClient != null) {
        //向服务器发送关闭连接的约定信息
        tcpClient.send("bye");
        tcpClient.close();
      }
    });
  }

  // 将Handler类作为内部类
  class Handler implements Runnable {
    private Socket socket;

    public Handler(Socket socket) {
      this.socket = socket;
    }

    @Override
    public void run() {
      //本地服务器控制台显示客户端连接的用户信息
      System.out.println("New connection accepted： " +
              socket.getInetAddress().getHostAddress());
      try {
        BufferedReader br = getReader(socket);//定义字符串输入流
        PrintWriter pw = getWriter(socket);//定义字符串输出流

        //客户端正常连接成功，则发送服务器欢迎信息，然后等待客户发送信息
        pw.println("From 服务器：欢迎使用本服务！");

        String msg = null;
        //此处程序阻塞，每次从输入流中读入一行字符串
        while ((msg = br.readLine()) != null) {
          //如果客户发送的消息为"bye"，就结束通信
          if (msg.trim().equalsIgnoreCase("bye")) {
            //向输出流中输出一行字符串,远程客户端可以读取该字符串
            pw.println("From 服务器：服务器已断开连接，结束服务！");
            System.out.println("客户端离开");
            break;//跳出循环读取
          }
          //向输出流中回传字符串,远程客户端可以读取该字符串
          pw.println("From 服务器：" + msg);
        }
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        try {
          if(socket != null)
            socket.close(); //关闭 socket 连接及相关的输入输出流
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    // 添加缺失的getReader方法
    private BufferedReader getReader(Socket socket) throws IOException {
      return new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }

    // 添加缺失的getWriter方法
    private PrintWriter getWriter(Socket socket) throws IOException {
      return new PrintWriter(socket.getOutputStream(), true);
    }
  }
}
